package com.ccn.qrcode.utils.qrcodefile;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import com.ccn.qrcode.common.Constant;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.media.imageio.plugins.tiff.TIFFTag;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.TIFFEncodeParam;
import com.sun.media.jai.codec.TIFFField;
import com.sun.media.jai.codecimpl.TIFFImageEncoder;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.*;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Arrays;

/**
 * 图片转换类， jpg 换成tiff
 *
 * @author tig
 */
public class ImageToTiffUtils {

    private static final Logger logger = LoggerFactory.getLogger(ImageToTiffUtils.class);

    public static String image2Tif(String fileAbsolutePath, String tifFilePath) {
        OutputStream outputStream = null;
        String filterFilePath = fileAbsolutePath.substring(0, fileAbsolutePath.lastIndexOf(".")) + "." + Constant.FORMAT;
        try {
            // 解决位深度太小 end
            FileSeekableStream stream = new FileSeekableStream(filterFilePath);
            PlanarImage in = JAI.create("stream", stream);
            OutputStream os = new FileOutputStream(tifFilePath);
            // 设置dpi为300
            TIFFEncodeParam param = new TIFFEncodeParam();
            param.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
            TIFFField[] extras = new TIFFField[2];
            extras[0] = new TIFFField(282, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) Constant.FILE_DPI, 1}, {0, 0}});
            extras[1] = new TIFFField(283, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) Constant.FILE_DPI, 1}, {0, 0}});
            param.setExtraFields(extras);
            TIFFImageEncoder enc = new TIFFImageEncoder(os, param);
            try {
                enc.encode(in);
                os.flush();
                os.close();
                stream.close();
            } catch (Exception e) {
                logger.error("{}", e);
                throw new RuntimeException(e);
            }
            return tifFilePath;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static void setDPI(IIOMetadata metadata, Integer dpi) throws IIOInvalidTreeException {
        double INCH_2_CM = 2.54d;
        // for PMG, it's dots per millimeter
        double dotsPerMilli = 1.0 * dpi / 10 / INCH_2_CM;
        IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
        horiz.setAttribute("value", Double.toString(dotsPerMilli));

        IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
        vert.setAttribute("value", Double.toString(dotsPerMilli));

        IIOMetadataNode dim = new IIOMetadataNode("Dimension");
        dim.appendChild(horiz);
        dim.appendChild(vert);

        IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
        root.appendChild(dim);

        metadata.mergeTree("javax_imageio_1.0", root);
    }



    /**
     *
     * 功能描述: 图片转tif格式
     *
     * @param: [fileAbsolutePath]
     * @return: java.lang.String  转成TIF图片的地址全路径
     * @auther: KevinZc
     * @date: 2018/9/8 22:14
     */
    public static String image2Tif(String fileAbsolutePath){
        OutputStream outputStream = null;
        String filterFilePath = null;
        String tifFilePath = null;
        ImageOutputStream ios = null;
        try {
            // 解决位深度太小 start ====注意：8位深度的图片会出现文件损坏问题
            File picture = new File(fileAbsolutePath);
            // 统一进行一次过滤 转换成24位深度
            filterFilePath = fileAbsolutePath.substring(0, fileAbsolutePath.lastIndexOf("."))+".png";
            tifFilePath = filterFilePath.substring(0, filterFilePath.lastIndexOf("."))+".tif";
            ios = ImageIO.createImageOutputStream(new File(filterFilePath));
            ImageIO.write(ImageIO.read(picture),"png", ios);
            // 解决位深度太小 end
            FileSeekableStream stream = new FileSeekableStream(filterFilePath);
            PlanarImage in = JAI.create("stream", stream);
            OutputStream os = null;
            os = new FileOutputStream(tifFilePath);
            // 设置dpi为300
            TIFFEncodeParam param = new TIFFEncodeParam();
            param.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
            TIFFField[] extras = new TIFFField[2];
            extras[0] = new TIFFField(282, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) 800, 1}, {0, 0}});
            extras[1] = new TIFFField(283, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) 800, 1}, {0, 0}});
            param.setExtraFields(extras);
            TIFFImageEncoder enc = new TIFFImageEncoder(os, param);
            try {
                enc.encode(in);
                os.flush();
                os.close();
                stream.close();
            } catch (Exception e) {
                logger.error("{}",e );
                throw new RuntimeException(e);
            }
            return tifFilePath;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (ios != null) {
                    ios.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    @SneakyThrows
    public static void main(String[] args) {
        zipCompress(null);
//        tt();
    }

    public static void tt() {
        File src = FileUtil.file("C:\\Users\\yyli45\\Desktop\\637833315394597062F0DB8.tiff");
        File dest = FileUtil.file("C:\\Users\\yyli45\\Desktop\\2.tiff");
        ImgUtil.scale(src, dest, 0.5f);
    }

    /**
     * 压缩文件大小，像素不变，文件缩小
     *
     * @param path 需要压缩文件的路径
     */
    @SneakyThrows
    public static void zipCompress(String path) {
        TIFFImageWriterSpi tiffws = new TIFFImageWriterSpi();
        ImageWriter writer = tiffws.createWriterInstance();

        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        System.out.println(Arrays.toString(param.getCompressionTypes()));

        // [CCITT RLE, CCITT T.4, CCITT T.6, LZW, JPEG, ZLib, PackBits, Deflate, EXIF JPEG]
        param.setCompressionType("LZW");
        param.setCompressionQuality(1.0f);
        File output = new File("/Users/tig/Desktop/中商/二维码-221013-221114/生成tiff/637833315394597062F0DB8111.tiff");
        ImageOutputStream ios = ImageIO.createImageOutputStream(output);
        writer.setOutput(ios);

        BufferedImage srcImage = ImageIO.read(new File("/Users/tig/Desktop/中商/二维码-221013-221114/生成tiff/637833315394597062F0DB8.tiff"));

        writer.write(null, new IIOImage(srcImage, null, null), param);

        handleDpi(output, 800, 800);
    }

    /**
     * 改变图片DPI
     *
     * @param xDensity 水平分辨率
     * @param yDensity 垂直分辨率
     */
    public static void handleDpi(File file, int xDensity, int yDensity) {
        FileOutputStream fileOutputStream = null;
        try {
            BufferedImage image = ImageIO.read(file);
            fileOutputStream = new FileOutputStream(file);
            JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(fileOutputStream);
            JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image);
            jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
            jpegEncoder.setJPEGEncodeParam(jpegEncodeParam);
            jpegEncodeParam.setQuality(1.0f, false);
            jpegEncodeParam.setXDensity(xDensity);
            jpegEncodeParam.setYDensity(yDensity);
            jpegEncoder.encode(image, jpegEncodeParam);
            image.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关流
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }





}

